﻿function ECommerceCartViewModel(context) {

    var self = this;

    var spinner = new SpinnerModel();

    var cart = context.cart;

    var productInfoRoute = context.spaRuntime.findRouteByName('product');

    var items = ko.computed(function () {
        var c = cart();
        if (c) return c.items();
        return null;
    });

    var recomendedProducts = new ECommerceRecommendationsViewModel(context);

    var cartItemSubscriptions = [];

    function disposeSubscriptions() {
        for (var i = 0; i < cartItemSubscriptions.length; i++) {
            cartItemSubscriptions[i].dispose();
        }
        cartItemSubscriptions = [];
    }

    function subscribeToItems() {
        var list = items();
        if (list) {
            for (var i = 0; i < list.length; i++) {
                var item = list[i];
                subscribeToItem(item);
            }
        }
    }

    function subscribeToItem(cartItem) {
        var subscription = cartItem.count.subscribe(function () {
            updateItem(cartItem);
        });
        cartItemSubscriptions.push(subscription);
    }

    function updateItem(cartItem) {
        var api = context.api();

        var info = cartItem.getInfo();
        if (cart()) {

            spinner.enter();
            api.cart.putItem(cartItem.id(), info, function (data) {
                spinner.leave();
            }, function () {
                spinner.leave();
            });
        }
    }

    function reloadRecommendations() {
        var c = cart();
        if (c) {
            var prods = c.items();
            var res = [];
            for (var i = 0; i < prods.length; i++) {
                var prod = prods[i];
                res.push(prod.id());
            }
            recomendedProducts.reload(res);
        }
    }

    function deleteItem(cartItem) {
        var api = context.api();

        var c = context.cart();
        if (c) {
            spinner.enter();
            api.cart.deleteItem(cartItem.id(), function (data) {
                spinner.leave();
                c.items.remove(cartItem);
                reloadRecommendations();
            }, function () {
                spinner.leave();
            });
        }
    }

    function checkout() {
        var api = context.api();

        var c = context.cart();
        if (c) {
            spinner.enter();
            api.cart.checkout(function () {
                spinner.leave();
                c.items([]);
                reloadRecommendations();

                var route = context.spaRuntime.findRouteByName('thankyou');
                route.navigateHash({});
            }, function () {
                spinner.leave();
            });
        }
    }


    function reload() {
        var api = context.api();
        disposeSubscriptions();

        spinner.enter();
        api.cart.get(function (data) {
            spinner.leave();
            cart(new ECommerceCart(data));
            subscribeToItems();
            reloadRecommendations();
        }, function () {
            spinner.leave();
        });
    }

    function getProductUrl(product) {
        return productInfoRoute.formatHash({
            id: product.id()
        });
    }

    self.items = items;
    self.reload = reload;
    self.deleteItem = deleteItem;
    self.getProductUrl = getProductUrl;
    self.checkout = checkout;
    self.recommendedProducts = recomendedProducts;
}

function ECommerceCart(cartInfo) {

    var self = this;

    var items = ko.observableArray([]);

    function findByProduct(id) {
        var cartItems = items();
        for (var i = 0; i < cartItems.length; i++) {
            var cartItem = cartItems[i];
            if (cartItem.id() == id) {
                return cartItem;
            }
        }
        return null;
    }

    function setInfo(info) {
        var array = info.items;

        var res = [];
        for (var i = 0; i < array.length; i++) {
            var itemInfo = array[i];
            var item = new ECommerceCartItem(itemInfo);
            res.push(item);
        }
        items(res);
    }

    var totalCount = ko.computed(function () {
        var list = items();
        var res = 0;
        for (var i = 0; i < list.length; i++) {
            var item = list[i];
            res += item.count();
        }
        return res;
    });

    if (cartInfo) {
        setInfo(cartInfo);
    }

    self.items = items;
    self.totalCount = totalCount;
    self.findByProduct = findByProduct;
    self.setInfo = setInfo;
}

function ECommerceCartItem(itemInfo) {

    var self = this;

    var id = ko.observable('');

    var title = ko.observable('');

    var description = ko.observable('');

    var imageUrl = ko.observable('');

    var itemPrice = ko.observable(0);

    var count = ko.observable(0);

    var price = ko.computed(function () {
        return itemPrice() * count();
    });

    var priceStr = ko.computed(function () {
        var pr = price();
        pr = Math.round(pr * 100);
        var rest = pr % 100;
        var a = (pr - rest) / 100;
        var res = a.toString();
        if (rest > 0) {
            res += '.';
            if (rest < 10) res += '0';
            res += rest;
        }
        return res;
    });

    function fromProduct(product) {
        id(product.id());
        title(product.title());
        itemPrice(product.price());
        count(0);
    }

    function getInfo() {
        return {
            prodId: id(),
            prodName: title(),
            prodDesc: description(),
            prodPrice: itemPrice(),
            quantity: count(),
            imageUrl: imageUrl()
        };
    }

    function setInfo(info) {
        id(info.prodId);
        title(info.prodName);
        description(info.prodDesc);
        itemPrice(info.prodPrice);
        count(info.quantity);
        imageUrl(info.imageUrl);
    }

    if (itemInfo) {
        setInfo(itemInfo);
    }

    self.id = id;
    self.title = title;
    self.itemPrice = itemPrice;
    self.count = count;
    self.price = price;
    self.priceStr = priceStr;
    self.fromProduct = fromProduct;
    self.getInfo = getInfo;
}